package demo.codeanalyzer.processor;

import java.util.List;
import java.util.Map;

import javax.lang.model.element.Element;
import javax.lang.model.element.Name;
import javax.lang.model.util.Elements;

import com.sun.source.tree.ClassTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.TreePath;
import com.sun.source.util.Trees;

public class GenericClassPrinter implements ClassPrinter {

	private final ClassTree classTree;

	private final Trees trees;

	private final PrintingVisitor visitor;

	private final Map<String, String> properties;

	private final String nameSpace;

	private String rdfLabel;

	private final boolean isVisible;

	public GenericClassPrinter(ClassTree classTree, Trees trees,
			PrintingVisitor visitor, Map<String, String> properties,
			Map<String, String> nameSpaces, String nameSpace, boolean isVisible) {
		this.classTree = classTree;
		this.trees = trees;
		this.visitor = visitor;
		this.properties = properties;
		this.nameSpace = nameSpace;
		this.isVisible = isVisible;
	}

	public Object print() {
		startClassDefinition();
		startSubClassDefinition();
		printLabel();
		Object result = visitor.visitParentClass(classTree, trees);
		endSubClassDefinition();
		endClassDefinition();
		printProperties();
		return result;
	}

	private void printLabel() {
		if (null != rdfLabel) {
			System.out.println(String.format("<rdfs:label>%s</rdfs:label>",
					unquote(rdfLabel)));
		}
	}

	private String unquote(String toUnquote) {
		return toUnquote.replace("\"", "");
	}

	private void printProperties() {
	}

	private void endSubClassDefinition() {
		// System.out.println("</rdfs:subClass> \n");
	}

	private void startSubClassDefinition() {
		handleSingleInheritence();
		handleMutipleInheritence();
		// System.out.println("<rdfs:subClassOf>");
	}

	private void handleMutipleInheritence() {
		List<? extends Tree> implementsClause = classTree.getImplementsClause();
		if (null != implementsClause) {
			System.out.println(subclass(classTree.getImplementsClause()
					.toString()));
		}
	}

	private void handleSingleInheritence() {
		Tree extendsClause = classTree.getExtendsClause();
		if (null != extendsClause) {
			System.out
					.println(subclass(classTree.getExtendsClause().toString()));
		}
	}

	private String subclass(String parentString) {
		String[] parents = parentString.split(",");
		StringBuilder result = new StringBuilder();
		String parent = null;
		for (int i = 0; i < parents.length; i++) {
			if (parents[i].equalsIgnoreCase("transparenteditableasset")
					|| parents[i].equalsIgnoreCase("editorialasset")) {
				parent = "&chs;" + parents[i];
			}
			if (parents[i].length() == 0) {
				parent = "&chs;" + "TransparentEditableAsset";
			}
			result.append(String.format("<rdfs:subClassOf %s /> \n",
					parent(parent)));
		}
		return result.toString();
	}

	private String parent(String parent) {
		return String.format("rdf:resource=\"%s\"", parent);
	}

	private void endClassDefinition() {
		System.out.println("</owl:Class> \n");
	}

	private void startClassDefinition() {
		System.out.print(owlClass(id(classTree.getSimpleName())));
		if (isVisible) {
			System.out.println(String.format(
					"<httph:content-type>%s</httph:content-type>",
					"application/rdf+xml"));
		}
	}

	private String owlClass(String id) {
		return String.format("<owl:Class %s > \n", id);
	}

	private String id(Name simpleName) {
		return String.format("rdf:about=\"%s%s\"", namespace(), simpleName
				.toString());
	}

	private String namespace() {
		return nameSpace;
	}

	protected Element element(Trees trees) {
		TreePath currentPath = visitor.getCurrentPath();
		Element element = trees.getElement(currentPath);
		return element;
	}

	public ClassPrinter label(String string) {
		this.rdfLabel = string;
		return this;
	}

}
